#include "sys/cdefs.h"
#include "syscalls.h"
#include <_ansi.h>
#include "sys/stat.h"
#include "errno.h"
#include "sys/stdarg.h"
#include "unistd.h"
#include "signal.h"
#include "sys/termios.h"
#include "sys/fcntl.h"
#include "sys/uio.h"
#include "sys/time.h"
#include "sys/times.h"
#include "sys/poll.h"
#include "sys/unistd.h"
#include "sys/vfs.h"
#include "sys/utsname.h"
#include "sys/dirent.h"
#include <utime.h>
#include <string.h>

//#include "sprintf.c"
//
extern void * malloc(size_t size);
extern void free(void *);

_syscall3(_READ_WRITE_RETURN_TYPE, read, int, fd, void *, buffer, size_t, count)
_syscall3(off_t, lseek, int, fd, off_t, offset, int, whence)
_syscall3(_READ_WRITE_RETURN_TYPE, write, int, fd, const void *, buffer, size_t, count)
_syscall1(int, close, int, fd)
_syscall1(int, brk, void *, end_data)
_syscall3(ssize_t, readv, int, fd, const struct iovec *, vec, int, count)
_syscall3(ssize_t, writev, int, fd, const struct iovec *, buf, int, count)
_syscall3(int, poll, struct pollfd *, fds, nfds_t, nfds, int, timeout)
_syscall2(int, statfs, const char *, path, struct statfs *, buf)
_syscall2(int, fstatfs, int, fd, struct statfs *, buf)
_syscall1(int, uname,struct utsname *, name)
_syscall2(int, truncate, const char *, path, off_t, size)
_syscall2(int, ftruncate, int, fd, off_t, size)
_syscall1(int, chroot, const char *, path)
_syscall1(int, init_module, const char *, name)
_syscall1(int, delete_module, const char *, name)

void * sbrk(ptrdiff_t incr)
{
	int ret, end_data = brk(0);

	if(!incr)
		return (caddr_t)end_data;

	ret = brk((void *)(end_data + incr));
	if((ret < 0) && (ret > (-4096))){
		errno = -ret;
		return (caddr_t)(-1);
	}

	return (caddr_t)end_data;
}

_syscall2(int, fstat, int, file, struct stat *, st)

int open(const char * filename, int flags, ...)
{
	int ret;
	mode_t mode;
	va_list args;

	va_start(args, flags);
	mode = va_arg(args, mode_t);
	va_end(args);

	ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_open), "b"(filename), "c"(flags), "d"(mode)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

#define MAJOR(dev)	((dev >> 8) & 0xff)
#define MINOR(dev)	(dev & 0xff)

int isatty(int fd)
{
	struct stat st;

	if(fstat(fd, &st) < 0)
		return 0;

	if(!S_ISCHR(st.st_mode))
		return 0;

	if(MAJOR(st.st_rdev) != 5)
		return 0;

  	return 1;
}

void _exit(int status)
{
	int ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_exit), "b"(status)
		);

	// avoid gcc warning
	while(1);
}

_syscall2(int, kill, pid_t, pid, int, sig)
_syscall0(int, getpid)
_syscall0(int ,getppid)
_syscall2(int, getgroups, int, size, gid_t *, list)
_syscall2(int, setgroups, int, size, const gid_t *, list)

int raise(int sig)
{
	pid_t pid = getpid();

	return kill(pid, sig);
}

_syscall2(int, stat, const char *, path, struct stat *, buf)
_syscall2(int, lstat, const char *, path, struct stat *, buf)
_syscall2(int, chmod, const char *, path, mode_t, mode)
_syscall2(int, fchmod, int, fd, mode_t, mode)
_syscall3(int, chown, const char *, path, short, owner, short, group)
_syscall3(int, fchown, int, fd, short, owner, short, group)
_syscall3(int, mknod, const char *, path, mode_t, mode, dev_t, dev)
_syscall0(pid_t, fork)
_syscall3(pid_t, waitpid, pid_t, pid, int *, status, int, option)

int execl(const char * pathname, const char * arg0, ...)
{
	int i, ret;
	va_list args;
	const char * argv[256];

	argv[0] = arg0;

	va_start(args, arg0);

	for(i = 1; i < 256; i++){
		argv[i] = va_arg(args, const char *);
		if(!argv[i])
			break;
	}

	va_end(args);

	argv[255] = NULL;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_execve), "b"(pathname), "c"(argv), "d"(environ)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int execv(const char * pathname, char * const argv[])
{
	int ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_execve), "b"(pathname), "c"(argv), "d"(environ)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int execle(const char * pathname, const char * arg0, ...)
{
	int i, ret;
	va_list args;
	const char * argv[256], * envp; // envp, just for no warning

	argv[0] = arg0;

	va_start(args, arg0);

	for(i = 1; i < 256; i++){
		argv[i] = va_arg(args, const char *);
		if(!argv[i])
			break;
	}

	if(argv[i]){
		const char * x;

		do{
			x = va_arg(args, const char *);
		}while(x);
	}

	envp = (char *)va_arg(args, char *);

	va_end(args);

	argv[255] = NULL;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_execve), "b"(pathname), "c"(argv), "d"(envp)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int execve(const char * pathname, char * const argv[], char * const envp[])
{
	int ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_execve), "b"(pathname), "c"(argv), "d"(envp)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int execlp(const char * filename, const char * arg0, ...)
{
	int i, ret;
	va_list args;
	const char * argv[256];

	argv[0] = arg0;

	va_start(args, arg0);

	for(i = 1; i < 256; i++){
		argv[i] = va_arg(args, const char *);
		if(!argv[i])
			break;
	}

	va_end(args);

	argv[255] = NULL;

	if((filename[0] == '/')
		|| ((filename[0] == '.') && (filename[1] == '/'))
		|| (
			(filename[0] == '.')
			&& (filename[1] == '.')
			&& (filename[2] == '/')
		   )
		){
		__asm__ __volatile__("int $0x80"
			:"=a"(ret)
			:"0"(__NR_execve),
			 "b"(filename), "c"(argv), "d"(environ)
			);
	}else{
		char pathname[128];

		strcpy(pathname, "/bin/");
		strcat(pathname, filename);

		__asm__ __volatile__("int $0x80"
			:"=a"(ret)
			:"0"(__NR_execve),
			 "b"(pathname), "c"(argv), "d"(environ)
			);
	}

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int execvp(const char * filename, char * const argv[])
{
	int ret = 0;

	if((filename[0] == '/')
		|| ((filename[0] == '.') && (filename[1] == '/'))
		|| (
			(filename[0] == '.')
			&& (filename[1] == '.')
			&& (filename[2] == '/')
		   )
		){
		__asm__ __volatile__("int $0x80"
			:"=a"(ret)
			:"0"(__NR_execve),
			 "b"(filename), "c"(argv), "d"(environ)
			);
	}else{
		char pathname[128];

		strcpy(pathname, "/bin/");
		strcat(pathname, filename);

		__asm__ __volatile__("int $0x80"
			:"=a"(ret)
			:"0"(__NR_execve),
			 "b"(pathname), "c"(argv), "d"(environ)
			);
	}

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

_syscall1(int, pipe, int *, filedes)

_syscall1(int, dup, int, fd)
_syscall2(int, dup2, int, oldfd, int, newfd)
_syscall2(int, mkdir, const char *, pathname, mode_t, mode)
_syscall1(int, rmdir, const char *, pathname)
_syscall1(int, chdir, const char *, path)
_syscall1(int, fchdir, int, fd)
_syscall2(int, link, const char *, oldpath, const char *, newpath)
_syscall1(int, unlink, const char *, filename)

int _rename(const char * oldpath, const char * newpath)
{
	int ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_rename), "b"(oldpath), "c"(newpath)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

_syscall2(int, symlink, const char *, oldpath, const char *, newpath)
_syscall3(int, readlink, const char *, path, char *, buff, size_t, bufsize)

_syscall1(unsigned int, alarm, unsigned int, seconds)
_syscall0(int, sync)

sighandler_t signal(int signum, sighandler_t handler)
{
	sighandler_t oldhandler;

	__asm__ __volatile__("int $0x80"
		:"=a"(oldhandler)
		:"0"(__NR_signal), "b"(signum), "c"(handler)
	       );
	
	return oldhandler;
}

_syscall0(int, pause)

int ioctl(int fd, int request, ...)
{
	int ret;
	void * data;
	va_list args;

	va_start(args, request);
	data = va_arg(args, void *);
	va_end(args);

	ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_ioctl), "b"(fd), "c"(request), "d"(data)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int fcntl(int fd, int request, ...)
{
	int ret;
	void * data;
	va_list args;

	va_start(args, request);
	data = va_arg(args, void *);
	va_end(args);

	ret = 0;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_fcntl), "b"(fd), "c"(request), "d"(data)
		);

	if(ret < 0){
		errno = -ret;
		return -1;
	}

	return ret;
}

int tcgetattr(int fd, struct termios * t)
{
	return ioctl(fd, TCGETA, t);
}

int tcsetattr(int fd, int request, const struct termios * t)
{
	return ioctl(fd, request, t);
}

int tcflow(int fd, int action)
{
	return ioctl(fd, TCXONC, action);
}

int tcflush(int fd, int queue_selector)
{
	return ioctl(fd, TCFLSH, queue_selector);
}

int tcsendbreak(int fd, int duration)
{
	return ioctl(fd, TCSBRK, duration);
}

int tcdrain(int fd)
{
	return ioctl(fd, TCSBRK, 0);
}

speed_t cfgetispeed(const struct termios * t)
{
	return t->c_ispeed;
}

speed_t cfgetospeed(const struct termios * t)
{
	return t->c_ospeed;
}

int cfsetispeed(struct termios * t, speed_t ispeed)
{
	t->c_ispeed = ispeed;
	return 0;
}

int cfsetospeed(struct termios * t, speed_t ospeed)
{
	t->c_ospeed = ospeed;
	return 0;
}

_syscall0(uid_t, getuid)
_syscall1(int, setuid, uid_t, uid)
_syscall0(uid_t, geteuid)
 
_syscall0(gid_t, getgid)
_syscall1(int, setgid, gid_t, gid)
_syscall0(gid_t, getegid)

_syscall2(int, setreuid, uid_t, ruid, uid_t, euid)
_syscall2(int, setregid, gid_t, rgid, gid_t, egid)

int seteuid(uid_t euid)
{
	return setreuid(-1, euid);
}

int setegid(gid_t egid)
{
	return setregid(-1, egid);
}


char * getcwd(char * buff, size_t size)
{
	int ret = 0;

	if(!buff){
		buff = (char *)malloc(512);
		if(!buff){
			errno = -ENOMEM;
			return NULL;
		}

		size = 512;
	}

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_getcwd), "b"(buff), "c"(size)
		);

	if(ret < 0){
		errno = -ret;
		return NULL;
	}

	return buff;
}

_syscall2(int, access, const char *, pathname, int, mode)

_syscall1(int, fsync, int, fd)

_syscall2(int, creat, const char *, pathname, mode_t, mode)

#include "sys/resource.h"

_syscall2(int, getrlimit, int, resource, struct rlimit *, rlim)
_syscall2(int, setrlimit, int, resource, const struct rlimit *, rlim)

#include "conf.c"

long sysconf(int name)
{
	struct rlimit rlim;

	if(name >= (sizeof(sc_max_values) / sizeof(long))){
		errno = -EINVAL;
		return -1;
	}

	if((name == _SC_CHILD_MAX) || (name == _SC_OPEN_MAX)){
		getrlimit(
			(name == _SC_CHILD_MAX) ? RLIMIT_NPROC: RLIMIT_NOFILE,
			&rlim
			);
		return rlim.rlim_cur;
	}
	
	return sc_max_values[name];
}

long fpathconf(int filedes, int name)
{
	if(name >= (sizeof(pc_max_values) / sizeof(long))){
		errno = -EINVAL;
		return -1;
	}

	return pc_max_values[name];
}

long pathconf(const char * path, int name)
{
	if(name >= (sizeof(pc_max_values) / sizeof(long))){
		errno = -EINVAL;
		return -1;
	}

	return pc_max_values[name];
}

long ulimit(int cmd, long newlimit)
{
	struct rlimit rlim;

	if(cmd == 3){
		getrlimit(RLIMIT_DATA, &rlim);
		return rlim.rlim_cur;
	}

	if(cmd == 4){
		getrlimit(RLIMIT_NOFILE, &rlim);
		return rlim.rlim_cur;
	}

	return -1;
}

char __ttyname[512];

char * ttyname(int fd)
{
	struct stat st, st1;
	DIR * d;
	struct dirent * dir;

	if(fstat(fd, &st) < 0)
		return NULL;

	if(!S_ISCHR(st.st_mode))
		return NULL;

	if(MAJOR(st.st_rdev) != 5)
		return NULL;

	d = opendir("/dev");
	if(!d)
		return NULL;

	strcpy(__ttyname, "/dev/");

	while((dir = readdir(d))){
		strcpy(&__ttyname[5], dir->d_name);

		if(stat(__ttyname, &st1) < 0)
			break;
		
		if(st.st_rdev == st1.st_rdev){
			closedir(d);
			return __ttyname;
		}
	}

	closedir(d);

	return NULL;
}

_syscall1(int, umask, mode_t, mode)

_syscall0(pid_t, getpgrp)
_syscall1(pid_t, getpgid, pid_t, pid)
_syscall2(int, setpgid, pid_t, pid, pid_t, pgid)

_syscall0(pid_t, setsid)
_syscall1(pid_t, getsid, pid_t, pid)

static void sig_alrm(int signo)
{
	return;
}

/* copy from aupe */
unsigned sleep(unsigned int seconds)
{
	struct sigaction newact;
	struct sigaction oldact;
	sigset_t oldmask;
	sigset_t newmask;
	sigset_t suspmask;
	unsigned int left;

	newact.sa_handler = sig_alrm;
	sigemptyset(&newact.sa_mask);
	newact.sa_flags = 0;
	sigaction(SIGALRM, &newact, &oldact);

	sigemptyset(&newmask);
	sigaddset(&newmask, SIGALRM);
	if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
	{
		return -1;
	}

	alarm(seconds);
	suspmask = oldmask;
	sigdelset(&suspmask, SIGALRM);
	sigsuspend(&suspmask);

	left = alarm(0);
	sigaction(SIGALRM, &oldact, NULL);
	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
	{
		return -1;
	}

	return left;
}

int wait(int *status)
{
	return waitpid(-1, status, 0);
}

_syscall1(time_t, time, time_t, t)
_syscall1(clock_t, times, struct tms *, buff)
_syscall2(int, settimeofday,
		const struct timeval *, tv, const struct timezone *, tz)
_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz)
_syscall3(int, getdents, int, fd, struct dirent *, dirp, int, count)
_syscall5(int, select, int, maxfdp1, fd_set *, readset, fd_set *, writeset, \
			fd_set *, exceptset, struct timeval *, timeout)
_syscall2(int, utime, const char *, path, const struct utimbuf *, buf)		

static char myhostname[128] = "host-unknown";

int gethostname(char * name, size_t len)
{
	strncpy(name, myhostname, len);
	return 0;
}

int sethostname(const char * name, size_t len)
{
	strncpy(myhostname, name, 128);
	return 0;
}

#include <pwd.h>

static int readline(int fd, char line[], int size)
{
	int i, len;

	if((len = read(fd, line, size)) < 0)
		return -1;

	// end of file
	if(!len)
		return 0;

	for(i = 0; i < len; i++)
		if(line[i] == '\n')
			break;

	// line too long
	if(i >= len){
		errno = ERANGE;
		return -1;
	}

	line[i] = '\0';

	lseek(fd, -len + i + 1, SEEK_CUR);

	return 1;
}

static char line[1024];
static struct passwd pwpasswd;

#define DOCOLON() \
	colon = strchr(colon, ':'); \
*colon = '\0'; \
colon++;

struct passwd * getpwnam(const char * name)
{
	int fd;
	char * colon;

	fd = open("/etc/passwd", O_RDONLY);
	if(fd < 0)
		return NULL;

	while(readline(fd, line, 1024) > 0){
		colon = line;

		pwpasswd.pw_name = line;
		DOCOLON()
			pwpasswd.pw_passwd = colon;
		DOCOLON()
			pwpasswd.pw_uid = atoi(colon);
		DOCOLON()
			pwpasswd.pw_gid = atoi(colon);
		DOCOLON()
			pwpasswd.pw_gecos = colon;
		DOCOLON()
			pwpasswd.pw_dir= colon;
		DOCOLON()
			pwpasswd.pw_shell = colon;

		if(!strcmp(name, pwpasswd.pw_name)){
			close(fd);
			return &pwpasswd;
		}
	}

	close(fd);

	errno = ENOENT;

	return NULL;
}

struct passwd * getpwuid(uid_t uid)
{
	int fd;
	char * colon;

	fd = open("/etc/passwd", O_RDONLY);
	if(fd < 0)
		return NULL;

	while(readline(fd, line, 1024) > 0){
		colon = line;

		pwpasswd.pw_name = line;
		DOCOLON()
			pwpasswd.pw_passwd = colon;	
		DOCOLON()
			pwpasswd.pw_uid = atoi(colon);
		DOCOLON()
			pwpasswd.pw_gid = atoi(colon);
		DOCOLON()
			pwpasswd.pw_gecos = colon;
		DOCOLON()
			pwpasswd.pw_dir= colon;
		DOCOLON()
			pwpasswd.pw_shell = colon;

		if(uid == pwpasswd.pw_uid){
			close(fd);
			return &pwpasswd;
		}
	}

	close(fd);

	errno = ENOENT;

	return NULL;
}


static int passwd_fd = -1;

struct passwd * getpwent(void)
{
	char * colon;

	if(passwd_fd < 0){
		passwd_fd = open("/etc/passwd", O_RDONLY);
		if(passwd_fd < 0)
			return NULL;
	}

	if(readline(passwd_fd, line, 1024) <= 0)
		return NULL;

	colon = line;

	pwpasswd.pw_name = line;
	DOCOLON()
		pwpasswd.pw_passwd = colon;	
	DOCOLON()
		pwpasswd.pw_uid = atoi(colon);
	DOCOLON()
		pwpasswd.pw_gid = atoi(colon);
	DOCOLON()
		pwpasswd.pw_gecos = colon;
	DOCOLON()
		pwpasswd.pw_dir= colon;
	DOCOLON()
		pwpasswd.pw_shell = colon;


	return &pwpasswd;
}

void setpwent(void)
{
	lseek(passwd_fd, 0, SEEK_SET);
}

void endpwent(void)
{
	close(passwd_fd);
	passwd_fd = -1;
}

size_t getpagesize(void)
{
	return 4096;
}

static char syslog_buf[1024];
static int syslog_idx = 0;

_syscall3(int,__syslog,int,type,char *,bufp,int,len)

void openlog(const char * ident, int option, int facility)
{
	sprintf(syslog_buf, "%s[%d]: ", ident, getpid());
	syslog_idx = strlen(syslog_buf);
}

static const char *check_pid_format(const char *format)
{
	const char *p;
	const char *q;
	int n = 0;

	p = strstr(format, "%m");
	if (!p)
	{
		return NULL;
	}

	/* get the count of countinous %  */
	q = p;
	while (--p >= format)
	{
		if (*p == '%')
		{
			n++;
		}
		else
		{
			break;
		}
	}

	if (n % 2)	// have even countinous %, check next.
	{
		return check_pid_format(q + 2);
	}
	else
	{
		return q;
	}
}

static int get_pid_fmt_count(const char *format)
{
	const char *p;
	const char *fmt = format;
	int n = 0;

	for (;;)
	{
		p = check_pid_format(fmt);
		if (!p)
		{
			break;
		}

		n++;
		fmt = p + 2;
	}

	return n;
}

/* substitute %m as getpid() */
static char *subs_pid_fmt(const char *format)
{
	int n;
	char *fmt;
	const char *src_ptr;
	char *dst_ptr;
	const char *p;
	int len;
	pid_t pid;
	char tmp[32];
	int tmp_len;	

	len = strlen(format);

	n = get_pid_fmt_count(format);
	if (n == 0)
	{	/* no substitute */
		fmt = (char *)malloc(len + 1);
		strcpy(fmt, format);

		return fmt;
	}
	
	pid = getpid();
	tmp_len = sprintf(tmp, "%d", pid);
	len += n * tmp_len;
	fmt = (char *)malloc(len + 1);
	*fmt = '\0';

	src_ptr = format;
	dst_ptr = fmt;
	for (;;)
	{
		p = check_pid_format(src_ptr);
		if (!p)
		{
			strcat(dst_ptr, src_ptr);
			break;
		}
		
		len = p - src_ptr;
		memcpy(dst_ptr, src_ptr, len);
		dst_ptr += len;
		memcpy(dst_ptr, tmp, tmp_len + 1); // copy pid 
		dst_ptr += tmp_len;
		src_ptr += len + 2;	// skip common format and %m
	}

	return fmt;
}

void vsyslog(int priority, const char *format, va_list ap)
{
	int len;
	const char *p;
	char *fmt;

	if (!(p = check_pid_format(format)))
	{
		len = vsprintf(&syslog_buf[syslog_idx], format, ap);
	}
	else
	{
		fmt = subs_pid_fmt(format);
		len = vsprintf(&syslog_buf[syslog_idx], fmt, ap);
		free(fmt);
	}

	/* test */
	len += syslog_idx;
	syslog_buf[len++] = '\n';
	syslog_buf[len] = '\0';

	__syslog(priority, syslog_buf, len);
}

void syslog(int priority, const char * format, ...)
{
	int len;
	va_list args;
	const char *p;
	char *fmt;

	va_start(args, format);

	if (!(p = check_pid_format(format)))
	{
		len = vsprintf(&syslog_buf[syslog_idx], format, args);
	}
	else
	{
		fmt = subs_pid_fmt(format);
		len = vsprintf(&syslog_buf[syslog_idx], fmt, args);
		free(fmt);
	}
	va_end(args);

	len += syslog_idx;
	syslog_buf[len++] = '\n';
	syslog_buf[len] = '\0';

	__syslog(priority, syslog_buf, len);	
}

void closelog(void)
{
	syslog_idx = 0;
}

void * mmap(
	void * start, size_t length, int prot, int flags, int fd, off_t offset
	)
{
	int ret;

	__asm__ __volatile__("int $0x80"
		:"=a"(ret)
		:"0"(__NR_mmap), "b"(&start)
	       );

	if((ret < 0) && (ret > (-4096))){
		errno = ret;
		return (void *)-1;
	}

	return (void *)ret;
}


int nanosleep(struct timespec *req, struct timespec *rem)
{
	struct timeval val;
	int ret;

	val.tv_sec = req->tv_sec;
	val.tv_usec = req->tv_nsec / 1000;

	ret = select(0, NULL, NULL, NULL, &val);

	rem->tv_sec = val.tv_sec;
	rem->tv_nsec = val.tv_usec * 1000;

	return ret;
}

_syscall2(int, munmap, void * , start, size_t, length)

_syscall3(int, ioperm, unsigned long, from, unsigned long, num, int, turn_on)
_syscall1(int, iopl, int, level)

_syscall3(
	int, mount, const char *, specialfile, const char *, dirname, int, flag
	);
_syscall1(int, umount, const char *, specialfile);

void libc_start_main(
		int (*pmain)(int, char **, char **),
		int argc,
		char ** ubp_av,
		void (*init)(void),
		void (*fini)(void),
		void (*rtld_fini)(void),
		void (*stack_end))
{
	environ = &ubp_av[argc + 1];
	pmain(argc, ubp_av, &ubp_av[argc + 1]);
	exit(0);
}
